﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "FamStructureTemplateDocument.h"
#include "IFamilyManager.h"
#include "IFamilyMultiDistanceDimension.h"
#include "IFamilyDistanceRatioConstraint.h"
#include "StructureInstanceSectionShapeType.h"
#include "GbmpBuiltInParameterStaticVauleListItems.h"
#include "IParameterValueDouble.h"
#include "IParameterValueInt.h"
#include "IParameterDefinitionLibrary.h"
#include "ReferencePlaneUtils.h"
#include "StructureInstanceSecondKeys.h"
#include "InstancePlacementTypes.h"
#include "FamStructureTemplateUtility.h"
#include "GcmpBuiltInCategoryUniIdentities.h"
#include "GbmpBuiltInParameterDefinitionsNew.h"
#include "IGraphicsNodeReference.h"
#include "IParameterValueString.h"
#include "IParameterValueDisplayString.h"
#include "IElementBasicInformation.h"
#include "IGenericElement.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "FamilyParameterType.h"
#include "IReferencePlane.h"
#include "IFamilyDistanceConstraint.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace gfam;

#define FAMILY_LEFT_REFERENCE_PLANE_NAME GBMP_TR(L"左")
#define FAMILY_RIGHT_REFERENCE_PLANE_NAME GBMP_TR(L"右")
#define FAMILY_LEFT_RIGHT_CENTER_REFERENCE_PLANE_NAME GBMP_TR(L"左右中心")
#define FAMILY_BACK_REFERENCE_PLANE_NAME GBMP_TR(L"后")
#define FAMILY_FRONT_REFERENCE_PLANE_NAME GBMP_TR(L"前")
#define FAMILY_FRONT_BACK_CENTER_REFERENCE_PLANE_NAME GBMP_TR(L"前后中心")
#define FAMILY_TOP_REFERENCE_PLANE_NAME GBMP_TR(L"顶")
#define FAMILY_BOTTOM_REFERENCE_PLANE_NAME GBMP_TR(L"底")
#define FAMILY_TOP_BOTTOM_CENTER_REFERENCE_PLANE_NAME GBMP_TR(L"上下中心")

//////////////////////////////////////////////////////////////////////////
bool FamStructureTemplateDocument::InitBeamTemplateFamilyDocument(gcmp::IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 放置类型，以便族服务更新扫掠体路径
    const IFamilyParameterDefinition* pPlacementTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPlacementTypeDef, L"pPlacementTypeDef为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPlacementTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnLevel));

    // 结构类型参数
    bool bOk = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)StructureType::CastInPlaceConcrete), PARAMETER_UID(StructureTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 梁类型参数
    bOk = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)StructureBeamType::Basic), PARAMETER_UID(CategorySubTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 梁的截面形状
    StructureInstanceSectionShapeType sectionType = StructureInstanceSectionShapeType::SECTION_SHAPE_INVALID;
    bOk = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create((int)sectionType), PARAMETER_UID(SectionShapeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建梁模板截面类型参数失败",L"GDMPLab",L"2024-03-30");

    // 截面宽度参数
    double profileWidth = 300;
    bOk = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(profileWidth), PARAMETER_UID(RectSectionWidthBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"FamStructureTemplateUtility::AddBuiltInParameterDefination失败",L"GDMPLab",L"2024-03-30");

    // 截面高度参数
    double profileHeight = 600;
    bOk = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(profileHeight), PARAMETER_UID(RectSectionHeightBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"FamStructureTemplateUtility::AddBuiltInParameterDefination失败",L"GDMPLab",L"2024-03-30");

    // Z轴定位线
    int zPositioningType = (int)BeamZPositioningType::Top;
    bOk = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDoc, IParameterValueInt::Create(zPositioningType), PARAMETER_UID(BeamZPositioningTypeBuiltInParameter), true, false, L"", ParameterProcessType::GeneralInput, FamilyParameterType::Integer);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 梁底面与上下中心面的偏移值，用于梁顶面或底面定位
    const std::wstring& zPositioningTypeName = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(BeamZPositioningTypeBuiltInParameter))->GetBasicInformation()->GetName();
    const std::wstring& profileHeightName = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter))->GetBasicInformation()->GetName();
    std::wstring bottomOffsetFormula;
    {
        // TODO: if条件中判断整形相等会出错
        // if (zPositioningTypeName=0, profileHeightName, 0)
        // bottomOffsetFormula = L"if (" + zPositioningTypeName + L"=0," + profileHeightName + L",0)";
        // 改用 bottomOffsetFormula = (1-zPositioningTypeName)*profileHeightName
        bottomOffsetFormula = L"(1-" + zPositioningTypeName + L")*" + profileHeightName;
    }
    double bottomOffset(0.0);
    {
        bottomOffset = profileHeight;
    }
    bOk = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(bottomOffset), PARAMETER_UID(BeamBottomOffsetBuiltInParameter), true, true, bottomOffsetFormula, ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    double dLength = 4000;
    bOk = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDoc, IParameterValueDouble::Create(dLength), PARAMETER_UID(StraightLineLengthBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralOutput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 添加参照平面
    FamStructureTemplateDocument::AddBeamFamilyTemplateReferencePlanes(pDoc);

    return true;
}

void gcmp::FamStructureTemplateDocument::AddBeamFamilyTemplateReferencePlanes(gcmp::IDocument* pDbDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");

    //线式族默认的参考线为从坐标系原点沿着X轴正方向，长度为“线式族长度”族参数标注的长度
    double dLength = 4000;
    double Rightlength = 750;
    double dBottomLength = 800;
    double secWidth = 600;
    double secHeight = 1000;

    //创建一个参照平面，添加标注
    Vector3d startPtY(dLength, Rightlength, 0);
    Vector3d endPtY(dLength, -Rightlength, 0);
    gcmp::IReferencePlane * pReferencePlaneRight = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, startPtY, endPtY, Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneRight != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneRight->GetBasicInformation()->SetName(FAMILY_RIGHT_REFERENCE_PLANE_NAME);
    pReferencePlaneRight->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Right);
    pReferencePlaneRight->SetVisibleUVMin(Vector2d(-Rightlength, -secHeight - FamilyTemplateConst::CommonExtend));
    pReferencePlaneRight->SetVisibleUVMax(Vector2d(Rightlength, FamilyTemplateConst::CommonExtend));

    gcmp::IReferencePlane * pReferencePlaneBottom = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(0, -dBottomLength, -secHeight), Vector3d(0, dBottomLength, -secHeight), Vector3d::UnitX);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneBottom != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneBottom->GetBasicInformation()->SetName(FAMILY_BOTTOM_REFERENCE_PLANE_NAME);
    pReferencePlaneBottom->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Bottom);
    pReferencePlaneBottom->SetVisibleUVMin(Vector2d(-dBottomLength, -FamilyTemplateConst::CommonExtend));
    pReferencePlaneBottom->SetVisibleUVMax(Vector2d(dBottomLength, dLength + FamilyTemplateConst::CommonExtend));

    gcmp::IReferencePlane * pReferencePlaneBack = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(-FamilyTemplateConst::CommonExtend, secWidth*0.5, 0), Vector3d(FamilyTemplateConst::CommonExtend, secWidth*0.5, 0), Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneBack != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneBack->GetBasicInformation()->SetName(FAMILY_BACK_REFERENCE_PLANE_NAME);
    pReferencePlaneBack->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Back);
    pReferencePlaneBack->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CommonExtend, -secHeight - FamilyTemplateConst::CommonExtend));
    pReferencePlaneBack->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend));

    gcmp::IReferencePlane * pReferencePlaneFront = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(-FamilyTemplateConst::CommonExtend, -secWidth*0.5, 0), Vector3d(FamilyTemplateConst::CommonExtend, -secWidth*0.5, 0), Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneFront != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneFront->GetBasicInformation()->SetName(FAMILY_FRONT_REFERENCE_PLANE_NAME);
    pReferencePlaneFront->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Front);
    pReferencePlaneFront->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CommonExtend, -secHeight - FamilyTemplateConst::CommonExtend));
    pReferencePlaneFront->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CommonExtend, FamilyTemplateConst::CommonExtend));

    std::vector<IReferencePlane*> allRefPlanes = IReferencePlane::GetAllReferencePlanes(pDbDoc);
    //获得默认的左右中心
    gcmp::IReferencePlane * pReferencePlaneLeftRightCenter = nullptr;
    gcmp::IReferencePlane * pReferencePlaneTopBottomCenter = nullptr;
    gcmp::IReferencePlane * pReferencePlaneFrontBackCenter = nullptr;

    FOR_EACH(pRefPlane, allRefPlanes)
    {
        if (pRefPlane->GetIsFixed() && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight)
        {
            pReferencePlaneLeftRightCenter = pRefPlane;
        }
        if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack)
        {
            pReferencePlaneFrontBackCenter = pRefPlane;
            pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend, -secHeight - FamilyTemplateConst::CenterExtend));
            pRefPlane->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CenterExtend, FamilyTemplateConst::CenterExtend));
        }
        if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfTopBottom)
        {
            pReferencePlaneTopBottomCenter = pRefPlane;
            pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterExtend, -FamilyTemplateConst::CenterLength*0.5));
            pRefPlane->SetVisibleUVMax(Vector2d(dLength + FamilyTemplateConst::CenterExtend, FamilyTemplateConst::CenterLength*0.5));
        }
    }
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneLeftRightCenter != nullptr, L"默认的Y参照平面为空",L"GDMPLab",L"2024-03-30");

    Coordinate3d coordXOY(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    Coordinate3d coordYOZ(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
    // 创建距离约束
    // 线式族长度约束
    if (pReferencePlaneLeftRightCenter != nullptr)
    {
        Vector3d dimPosition(dLength / 2, secWidth*0.5 + FamilyTemplateConst::CenterExtend, 0);
        gfam::IFamilyDistanceConstraint* pDistanceConstraint = FamStructureTemplateUtility::CreateDistanceConstraint(pDbDoc, pReferencePlaneRight, pReferencePlaneLeftRightCenter, coordXOY, dimPosition);
        pDistanceConstraint->CalcDimValue();

        gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
        const gfam::IFamilyParameterDefinition* pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(StraightLineLengthBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraint->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
    }

    // 截面高度
    if (pReferencePlaneTopBottomCenter)
    {
        Vector3d dimPosition(0, secWidth*0.5 + FamilyTemplateConst::CenterExtend, -secHeight*0.5);
        gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
        gfam::IFamilyDistanceConstraint* pDistanceConstraintHeight = FamStructureTemplateUtility::CreateDistanceConstraint(pDbDoc, pReferencePlaneBottom, pReferencePlaneTopBottomCenter, coordYOZ, dimPosition);
        pDistanceConstraintHeight->CalcDimValue();

        gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
        const IFamilyParameterDefinition*  pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraintHeight->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
    }

    // 截面宽度
    if (pReferencePlaneFrontBackCenter)
    {
        Vector3d dimPosition(0, 0, FamilyTemplateConst::CommonExtend);
        gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
        gfam::IFamilyDistanceConstraint* pDistanceConstraintWidth = FamStructureTemplateUtility::CreateDistanceConstraint(pDbDoc, pReferencePlaneBack, pReferencePlaneFront, coordYOZ, dimPosition);
        pDistanceConstraintWidth->CalcDimValue();

        gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
        const IFamilyParameterDefinition*  pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionWidthBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraintWidth->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());

        Vector3d dimPositionEqual(0, 0, -secHeight - FamilyTemplateConst::CommonExtend);
        IFamilyMultiDistanceDimension*pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), coordYOZ, true);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pReferencePlaneFront->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pReferencePlaneBack->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

        IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), coordYOZ);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pReferencePlaneFront->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pReferencePlaneBack->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
        pEqualConstraint->SetRatioValue(0.5);

        pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
    }
    return;
}

bool gcmp::FamStructureTemplateDocument::InitColumnTemplateFamilyDocument(gcmp::IDocument* pDbDoc)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    // 结构类型参数
    bool result = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create((int)StructureType::CastInPlaceConcrete), PARAMETER_UID(StructureTypeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(result, L"创建结构类型参数失败",L"GDMPLab",L"2024-03-30");

    //设置放置类型
    const IFamilyParameterDefinition*  pPosTypeDef = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(InstancePlacementTypeBuiltInParamter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPosTypeDef != nullptr, L"InstancePlacementTypeBuiltInParamter参数定义为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->SetParameterValueStorage(pPosTypeDef, IParameterValueInt::Create((int)InstancePlacementTypes::OnLevel));

    // 高度参数
    double height = 3000;
    result = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(height), PARAMETER_UID(ColumnHeightBuiltInParameter), true, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(result, L"柱高度参数添加失败",L"GDMPLab",L"2024-03-30");

    // 截面形状
    StructureInstanceSectionShapeType sectionType = StructureInstanceSectionShapeType::SECTION_SHAPE_INVALID;
    result = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDbDoc, IParameterValueInt::Create((int)sectionType), PARAMETER_UID(SectionShapeBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(result, L"创建参数失败",L"GDMPLab",L"2024-03-30");

    // 截面高度
    double sectionHeight = 800;
    result = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(sectionHeight), PARAMETER_UID(RectSectionHeightBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(result, L"柱截面高度参数添加失败",L"GDMPLab",L"2024-03-30");

    // 截面宽度
    double sectionWidth = 600;
    result = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(sectionWidth), PARAMETER_UID(RectSectionWidthBuiltInParameter), false, false, L"", gcmp::ParameterProcessType::GeneralInput, FamilyParameterType::Length);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(result, L"柱截面宽度参数添加失败",L"GDMPLab",L"2024-03-30");

    // 截面旋转
    double sectionAngle = 0;
    result = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(sectionAngle), PARAMETER_UID(SectionRotateAngleBuiltInParameter), true, false, L"", ParameterProcessType::GeneralInput, FamilyParameterType::Angle);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(result, L"柱截面旋转参数添加失败",L"GDMPLab",L"2024-03-30");
    // 倾斜角度
    double angle = 0;
    result = FamStructureTemplateUtility::AddBuiltInParameterDefination(pDbDoc, IParameterValueDouble::Create(angle), PARAMETER_UID(ColumnAngleBuiltInParameter), true, false, L"", ParameterProcessType::GeneralOutput, FamilyParameterType::Angle);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(result, L"柱倾斜角度参数添加失败",L"GDMPLab",L"2024-03-30");

    return true;
}

void gcmp::FamStructureTemplateDocument::AddColumnFamilyTemplateReferencePlanes(gcmp::IDocument* pDbDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空",L"GDMPLab",L"2024-03-30");
    gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
    //创建参照平面
    const IFamilyParameterDefinition*  pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(ColumnHeightBuiltInParameter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
    // 参数定义
    double dimValue = 3000;
    double referencePlaneLength = 10000;
    double secWidth = 600;
    double secHeight = 800;
    double columnHeight = 3000;
    double frontBackPlaneLength = 1400;
    double frontBackCenterPlaneLength = 1600;
    double leftRightPlaneLength = 1600;
    double leftRightCenterPlaneLength = 1800;

    // 创建 前、后、左、右、顶、底参照平面并设置可见范围
    // 前
    gcmp::IReferencePlane * pReferencePlaneFront = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(-1, -secHeight / 2, columnHeight * 0.5), Vector3d(1, -secHeight * 0.5, columnHeight * 0.5), Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneFront != nullptr, L"创建“前”参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneFront->GetBasicInformation()->SetName(FAMILY_FRONT_REFERENCE_PLANE_NAME);
    pReferencePlaneFront->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Front);
    pReferencePlaneFront->SetVisibleUVMin(Vector2d(-frontBackPlaneLength * 0.5, -columnHeight / 2 - FamilyTemplateConst::CommonExtend));
    pReferencePlaneFront->SetVisibleUVMax(Vector2d(frontBackPlaneLength * 0.5, columnHeight * 0.5 + FamilyTemplateConst::CommonExtend));
    // 后
    gcmp::IReferencePlane * pReferencePlaneBack = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(-1, secHeight / 2, columnHeight * 0.5), Vector3d(1, secHeight * 0.5, columnHeight * 0.5), Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneBack != nullptr, L"创建“后”参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneBack->GetBasicInformation()->SetName(FAMILY_BACK_REFERENCE_PLANE_NAME);
    pReferencePlaneBack->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Back);
    pReferencePlaneBack->SetVisibleUVMin(Vector2d(-frontBackPlaneLength * 0.5, -columnHeight * 0.5 - FamilyTemplateConst::CommonExtend));
    pReferencePlaneBack->SetVisibleUVMax(Vector2d(frontBackPlaneLength * 0.5, columnHeight * 0.5 + FamilyTemplateConst::CommonExtend));
    // 左
    gcmp::IReferencePlane * pReferencePlaneLeft = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(-secWidth * 0.5, -1, columnHeight * 0.5), Vector3d(-secWidth * 0.5, 1, columnHeight * 0.5), Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneLeft != nullptr, L"创建“左”参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneLeft->GetBasicInformation()->SetName(FAMILY_LEFT_REFERENCE_PLANE_NAME);
    pReferencePlaneLeft->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Left);
    pReferencePlaneLeft->SetVisibleUVMin(Vector2d(-leftRightPlaneLength * 0.5, -columnHeight * 0.5 - FamilyTemplateConst::CommonExtend));
    pReferencePlaneLeft->SetVisibleUVMax(Vector2d(leftRightPlaneLength * 0.5, columnHeight * 0.5 + FamilyTemplateConst::CommonExtend));
    // 右
    gcmp::IReferencePlane * pReferencePlaneRight = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(secWidth * 0.5, -1, columnHeight * 0.5), Vector3d(secWidth * 0.5, 1, columnHeight * 0.5), Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneRight != nullptr, L"创建“后”参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneRight->GetBasicInformation()->SetName(FAMILY_RIGHT_REFERENCE_PLANE_NAME);
    pReferencePlaneRight->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Right);
    pReferencePlaneRight->SetVisibleUVMin(Vector2d(-leftRightPlaneLength * 0.5, -columnHeight * 0.5 - FamilyTemplateConst::CommonExtend));
    pReferencePlaneRight->SetVisibleUVMax(Vector2d(leftRightPlaneLength * 0.5, columnHeight * 0.5 + FamilyTemplateConst::CommonExtend));
    // 顶
    gcmp::IReferencePlane * pReferencePlaneTop = gcmp::ReferencePlaneUtils::CreateByPoints(pDbDoc, Vector3d(-1, 0, columnHeight), Vector3d(1, 0, columnHeight), Vector3d::UnitY);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferencePlaneTop != nullptr, L"创建“顶”参照平面失败",L"GDMPLab",L"2024-03-30");
    pReferencePlaneTop->GetBasicInformation()->SetName(FAMILY_TOP_REFERENCE_PLANE_NAME);
    pReferencePlaneTop->SetProjectReferenceType(ProjectReferenceTypeOfReferencePlane::Top);
    pReferencePlaneTop->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterLength * 0.5, -FamilyTemplateConst::CenterLength * 0.5));
    pReferencePlaneTop->SetVisibleUVMax(Vector2d(FamilyTemplateConst::CenterLength * 0.5, FamilyTemplateConst::CenterLength * 0.5));

    // 设置左右、上下中心面的可见范围

    std::vector<IElement*> allRefPlanes = pDbDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_REFERENCE_PLANE);
    //获得默认的左右中心
    gcmp::IReferencePlane * pReferencePlaneLeftRightCenter = nullptr;
    gcmp::IReferencePlane * pReferencePlaneTopBottomCenter = nullptr;
    gcmp::IReferencePlane * pReferencePlaneFrontBackCenter = nullptr;

    FOR_EACH(pItem, allRefPlanes)
    {
        IReferencePlane * pRefPlane = quick_cast<IReferencePlane>(pItem);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pRefPlane != nullptr, L"pRefPlane为空",L"GDMPLab",L"2024-03-30");

        if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight)
        {
            pReferencePlaneLeftRightCenter = pRefPlane;
            pReferencePlaneLeftRightCenter->SetVisibleUVMin(Vector2d(-leftRightCenterPlaneLength * 0.5, -FamilyTemplateConst::CenterExtend));
            pReferencePlaneLeftRightCenter->SetVisibleUVMax(Vector2d(leftRightCenterPlaneLength * 0.5, columnHeight + FamilyTemplateConst::CenterExtend));
        }
        if (pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack)
        {
            pReferencePlaneFrontBackCenter = pRefPlane;
            pReferencePlaneFrontBackCenter->SetVisibleUVMin(Vector2d(-frontBackCenterPlaneLength * 0.5, -FamilyTemplateConst::CenterExtend));
            pReferencePlaneFrontBackCenter->SetVisibleUVMax(Vector2d(frontBackCenterPlaneLength * 0.5, columnHeight + FamilyTemplateConst::CenterExtend));
        }
        if (pRefPlane->GetIsFixed() && pRefPlane->GetProjectReferenceType() == ProjectReferenceTypeOfReferencePlane::CenterOfTopBottom)
        {
            pReferencePlaneTopBottomCenter = pRefPlane;
            pRefPlane->SetVisibleUVMin(Vector2d(-FamilyTemplateConst::CenterLength*0.5, -FamilyTemplateConst::CenterLength*0.5));
            pRefPlane->SetVisibleUVMax(Vector2d(FamilyTemplateConst::CenterLength*0.5, FamilyTemplateConst::CenterLength*0.5));
        }
    }
    // 创建 参照平面之间的约束
    Coordinate3d coordXOZ(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitZ);
    Coordinate3d coordXOY(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitY);
    Coordinate3d coordYOZ(Vector3d::Zero, Vector3d::UnitY, Vector3d::UnitZ);
    //高度距离约束
    if (pReferencePlaneTopBottomCenter != nullptr)
    {
        Vector3d dimPosition(referencePlaneLength * 0.5, 0, dimValue * 0.25);
        double dimScale = 200;
        IFamilyMultiDistanceDimension*pDim = nullptr;
        IFamilyDistanceConstraint*pDistanceConstraint = FamStructureTemplateUtility::CreateDistanceConstraint(pDbDoc, pReferencePlaneTop, pReferencePlaneTopBottomCenter, coordXOZ, dimPosition);
        pDistanceConstraint->CalcDimValue();
        pDistanceConstraint->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());
    }
    // 截面宽度约束
    if (pReferencePlaneLeftRightCenter)
    {
        Vector3d dimPosition(0, leftRightCenterPlaneLength*0.5, 0);
        gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
        gfam::IFamilyDistanceConstraint* pDistanceConstraintWidth = FamStructureTemplateUtility::CreateDistanceConstraint(pDbDoc, pReferencePlaneLeft, pReferencePlaneRight, coordXOY, dimPosition);
        pDistanceConstraintWidth->CalcDimValue();

        gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
        const IFamilyParameterDefinition*  pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionWidthBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraintWidth->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());

        Vector3d dimPositionEqual(0, -leftRightCenterPlaneLength*0.5, 0);
        IFamilyMultiDistanceDimension*pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), coordXOY, true);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pReferencePlaneLeft->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pReferencePlaneLeftRightCenter->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pReferencePlaneRight->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

        IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), coordXOY);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pReferencePlaneLeft->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pReferencePlaneLeftRightCenter->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pReferencePlaneRight->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
        pEqualConstraint->SetRatioValue(0.5);

        pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
    }
    // 截面高度约束
    if (pReferencePlaneFrontBackCenter)
    {
        Vector3d dimPosition(frontBackCenterPlaneLength*0.5, 0, 0);
        gfam::IFamilyMultiDistanceDimension* pDim = nullptr;
        gfam::IFamilyDistanceConstraint* pDistanceConstraintWidth = FamStructureTemplateUtility::CreateDistanceConstraint(pDbDoc, pReferencePlaneBack, pReferencePlaneFront, coordXOY, dimPosition); 
        pDistanceConstraintWidth->CalcDimValue();

        gfam::IFamilyManager* pFamilyManager = IFamilyManager::Get(pDbDoc);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
        const IFamilyParameterDefinition*  pFamParameterDefinition = pFamilyManager->GetFamilyParameterDefinition(PARAMETER_UID(RectSectionHeightBuiltInParameter));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamParameterDefinition != nullptr, L"pFamParameterDefinition为空",L"GDMPLab",L"2024-03-30");
        pDistanceConstraintWidth->SetFamilyParameterDefinitionId(pFamParameterDefinition->GetElementId());

        Vector3d dimPositionEqual(-frontBackCenterPlaneLength*0.5, 0, 0);
        IFamilyMultiDistanceDimension*pDimEqual = IFamilyMultiDistanceDimension::Create(pDbDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), coordXOY, true);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(pReferencePlaneFront->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pReferencePlaneBack->GetElementId(), GraphicsNodeId(1));
        pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

        IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDbDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), coordXOY);
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(pReferencePlaneFront->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pReferencePlaneFrontBackCenter->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
        gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pReferencePlaneBack->GetElementId(), GraphicsNodeId(1));
        pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
        pEqualConstraint->SetRatioValue(0.5);

        pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());
    }
}
